package com.junxonline.instant.admin.service.config.impl;

import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.gson.reflect.TypeToken;
import com.junxonline.instant.common.util.common.RedisUtils;
import com.junxonline.instant.dao.entity.dto.ui.SelectNodeDTO;
import com.junxonline.instant.dao.entity.model.config.Dict;
import com.junxonline.instant.dao.entity.model.config.DictGroup;
import com.junxonline.instant.dao.entity.vo.config.DictVO;
import com.junxonline.instant.dao.mapper.config.DictGroupMapper;
import com.junxonline.instant.dao.mapper.config.DictMapper;
import com.junxonline.instant.admin.service.config.DictService;
import com.junxonline.instant.common.constant.RedisConstant;
import com.junxonline.instant.common.entity.common.CommonReqPage;
import com.junxonline.instant.common.entity.common.CommonRespPage;
import com.junxonline.instant.common.enumeration.AdminErrorEnum;
import com.junxonline.instant.common.exception.AdminBizException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * 数据字典接口实现类
 *
 * @author JunX
 * @date 2021-07-18
 */
@Service
@Transactional
public class DictServiceImpl extends ServiceImpl<DictMapper, Dict> implements DictService {

    @Autowired
    private RedisUtils redisUtils;

    @Autowired
    private DictGroupMapper dictGroupMapper;

    @Autowired
    private DictMapper dictMapper;

    /**
     * 根据数据字典分组查询数据字典列表（Select）
     *
     * @param code 数据字典分组编码
     * @return List<SelectNodeDTO>
     */
    @Override
    public List<SelectNodeDTO> queryDictByGroupCode(String code) {
        List<SelectNodeDTO> selectNodeDTOList = new ArrayList<>();
        if (redisUtils.hasKey(RedisConstant.KEY_DICT + code)) {
            String dictListJson = (String) redisUtils.get(RedisConstant.KEY_DICT + code);
            List<Dict> dictList = JSON.parseObject(dictListJson, new TypeToken<List<Dict>>(){}.getType());
            // 排序
            dictList.sort((d1, d2) -> {
                Integer s1 = d1.getSort();
                Integer s2 = d2.getSort();
                return s1.compareTo(s2);
            });
            long id = 0L;
            for (Dict dict : dictList) {
                String key = dict.getValue();
                String value = dict.getLabel();
                SelectNodeDTO dto = new SelectNodeDTO(id++, key, value);
                selectNodeDTOList.add(dto);
            }
            return selectNodeDTOList;
        } else {
            return Collections.emptyList();
        }
    }

    /**
     * 查询数据字典列表
     *
     * @param vo 请求对象
     * @return CommonRespPage<Dict>
     */
    @Override
    @SuppressWarnings("unchecked")
    public CommonRespPage<Dict> queryList(CommonReqPage<DictVO> vo) {
        LambdaQueryWrapper<Dict> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Dict::getParentId, vo.getQueryParams().getParentId());
        wrapper.like(!StrUtil.isBlank(vo.getQueryParams().getLabel()), Dict::getLabel, vo.getQueryParams().getLabel());
        wrapper.eq(vo.getQueryParams().getStatus() != null, Dict::getStatus, vo.getQueryParams().getStatus());
        wrapper.orderByAsc(Dict::getSort);
        return CommonRespPage.success(dictMapper.selectPage(new Page<>(vo.getPage(), vo.getPageSize()), wrapper));
    }

    /**
     * 查询数据字典
     *
     * @param id ID
     * @return Dict
     */
    @Override
    public Dict query(Long id) {
        Dict dict = dictMapper.selectById(id);
        Assert.notNull(dict, AdminErrorEnum.DATA_IS_NOT_EXISTS.getMsg());
        return dict;
    }

    /**
     * 新增数据字典
     *
     * @param dict 请求参数
     */
    @Override
    public void add(Dict dict) {
        Integer count = dictMapper.selectCount(new LambdaQueryWrapper<Dict>().eq(Dict::getValue, dict.getValue()).eq(Dict::getParentId, dict.getParentId()));
        if (count > 0) {
            throw new AdminBizException(AdminErrorEnum.DATA_IS_EXISTS);
        }
        dictMapper.insert(dict);
        // 获取数据字典分组的code
        DictGroup dictGroup = dictGroupMapper.selectById(dict.getParentId());
        // 往缓存中新增数据
        List<Dict> dictList = dictMapper.selectList(new LambdaQueryWrapper<Dict>().eq(Dict::getParentId, dictGroup.getId()));
        redisUtils.set(RedisConstant.KEY_DICT + dictGroup.getCode(), JSON.toJSONString(dictList));
    }

    /**
     * 编辑数据字典
     *
     * @param dict 请求参数
     */
    @Override
    public void edit(Dict dict) {
        Integer count = dictMapper.selectCount(new LambdaQueryWrapper<Dict>()
                .ne(Dict::getId, dict.getId())
                .eq(Dict::getValue, dict.getValue())
                .eq(Dict::getParentId, dict.getParentId()));
        if (count > 0) {
            throw new AdminBizException(AdminErrorEnum.DATA_IS_EXISTS);
        }
        dictMapper.updateById(dict);
        // 获取数据字典分组的code
        DictGroup dictGroup = dictGroupMapper.selectById(dict.getParentId());
        // 更新缓存中的数据
        List<Dict> dictList = dictMapper.selectList(new LambdaQueryWrapper<Dict>().eq(Dict::getParentId, dictGroup.getId()));
        redisUtils.set(RedisConstant.KEY_DICT + dictGroup.getCode(), JSON.toJSONString(dictList));
    }

    /**
     * 删除数据字典
     *
     * @param ids 请求参数
     */
    @Override
    public void delete(List<Long> ids) {
        List<Dict> dictList = dictMapper.selectBatchIds(ids);
        for (Dict dict : dictList) {
            // 删除数据库中的数据
            dictMapper.deleteById(dict.getId());
            // 获取数据字典分组的code
            DictGroup dictGroup = dictGroupMapper.selectById(dict.getParentId());
            // 更新缓存中的数据
            List<Dict> realDictList = dictMapper.selectList(new LambdaQueryWrapper<Dict>().eq(Dict::getParentId, dictGroup.getId()));
            redisUtils.set(RedisConstant.KEY_DICT + dictGroup.getCode(), JSON.toJSONString(realDictList));
        }

    }

}
